﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;

namespace ExecutionContract
{
    public class ExecutionContractServerSideGenerator
    {
        public static char[] Separators = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
        
        public string GenerateStringValue(string _path, MethodInfo _methodInfo)
        {
            FileStream fileStream = File.OpenRead(_path);
            StreamReader reader = new StreamReader(fileStream);
            string className = _methodInfo.DeclaringType.Name;
            string methodName = _methodInfo.Name;

            string line;
            string result = "";
            while ((line = reader.ReadLine()) != null)
            {
                if (line.Contains(className) && line.Contains("class"))
                {
                    line = line.Substring(line.IndexOf(className) + className.Length);
                    //check if the current line contains more then just the class definition
                    if (line.Contains(']') && line.Contains('{'))
                    {

                    }
                    else
                    {
                        result += ReadToReachCLass(reader, methodName);
                    }
                }
            }
            byte[] byteArray = Encoding.ASCII.GetBytes(result);
            string text = "";
          
            Random rnd = new Random(new DateTime().Second);
            for (int i = 0; i < byteArray.Length; i++)
            {
                char ch = Separators[rnd.Next(Separators.Length)];
                text += byteArray[i] + ch.ToString();
            }
            text = text.Substring(0, text.Length - 1);

            return text;
        }
        /// <summary>
        /// This method goes until it reaches the first '{'
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        private static string ReadToReachCLass(StreamReader reader, string _methodName)
        {
            char charVal;
            string result = "";
            while ((charVal = (char)reader.Read()) != null)
            {
                if (charVal.Equals('{'))
                {
                    result += ReadInClass(reader, _methodName);
                    return result;
                }
            }
            return result;
        }
        /// <summary>
        /// This method reads in the class and checks where the search method is located.
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        private static string ReadInClass(StreamReader reader, string _methodName)
        {
            char charVal;
            string tempWord = "";
            Stack<char> counter = new Stack<char>();
            string result = "";
            while (reader.Peek() >= 0)
            {
                charVal = (char)reader.Read();
                //case of comment
                if (charVal.Equals('/'))
                {
                    charVal = (char)reader.Read();
                    if (charVal.Equals('/'))
                    {
                        //jump over the hole line that is in the comment we found
                        reader.ReadLine();
                        charVal = (char)reader.Read();
                    }
                    else
                    {
                        if (charVal.Equals('*'))
                        {
                            bool goOn = true;
                            //we have to go to end of comment
                            while (goOn)
                            {
                                charVal = (char)reader.Read();
                                if (charVal.Equals('*'))
                                {
                                    charVal = (char)reader.Read();
                                    if (charVal.Equals('/'))
                                    {
                                        //end search for comment
                                        goOn = false;
                                        charVal = (char)reader.Read();
                                    }
                                }
                            }
                        }
                    }
                }

                if (charVal.Equals('{'))
                {
                    counter.Push(charVal);
                }
                else
                {
                    if (charVal.Equals('}'))
                    {
                        counter.Pop();
                    }
                    else
                    {

                        if (charVal.Equals(' '))
                        {
                            tempWord = "";
                        }
                        else
                        {
                            tempWord += charVal;
                        }
                    }
                }

                //check if the tempWord is the method we are looking for  and if the syntax is correct
                if (tempWord.Equals(_methodName) && counter.Count == 0)
                {
                    result = ReadToReachMethod(reader);
                    return result;
                }
            }

            return result;
        }

        private static string ReadToReachMethod(StreamReader reader)
        {
            char charVal;
            string result = "";
            while (reader.Peek() >= 0)
            {
                charVal = (char)reader.Read();
                if (charVal.Equals('{'))
                {
                    result = ReadMethod(reader);
                    return result;
                }
            }

            return result;
        }

        private static string ReadMethod(StreamReader reader)
        {
            char charVal;
            string result = "";
            Stack<char> counter = new Stack<char>();
            counter.Push('{');
            while (reader.Peek() >= 0)
            //while ((charVal = (char)reader.Read()) != null)
            {
                charVal = (char)reader.Read();
                if (charVal.Equals('{'))
                {
                    counter.Push(charVal);
                }
                else
                {
                    if (charVal.Equals('}'))
                    {
                        counter.Pop();
                        //check if the stack is empty
                        if (counter.Count == 0)
                        {
                            //we are finshed.
                            return result;
                        }
                    }
                }
                result += charVal;
            }

            return result;
        }
    }
}
